#include <GL/glut.h>
#include <math.h>
#include <time.h>
#include <stdio.h>

//月球单位半径
#define R_Moon  20000
//地球半径
#define R_Earth 50000
//太阳半径
#define R_Sun   200000
//地月距离
#define S_EM    200000
//一天文单位
#define S_SE    1000000

static double day=123; //范围0-359

double CalFrequency()
{
    static int count;
    static double save;
    static clock_t last, current;
    double timegap;

    ++count;
    if( count <= 50 )
        return save;
    count = 0;
    last = current;
    current = clock();
    timegap = (current-last)/(double)CLOCKS_PER_SEC;
    save = 50.0/timegap;
    return save;
}


static double Mult_X=1.5;
static double Mult_Y=1.5;
static double Mult_Z=1.5;

void myDisplay(void)
{
    double FPS = CalFrequency();
    printf("FPS = %f\n", FPS);

    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //设置观察参数，参数：视野角度，宽高比，最近距离，最远距离
    gluPerspective(75,1,1,S_SE*100);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    //设置观察位置
    gluLookAt(S_SE*Mult_X, S_SE*Mult_Y, S_SE*Mult_Z, 0, 0, 0, 0, 0, 1);


    // 定义太阳光源，它是一种白色的光源
    {
        GLfloat sun_light_position[] = {0.0f, 0.0f, 0.0f, 1.0f};
        GLfloat sun_light_ambient[]   = {0.0f, 0.0f, 0.0f, 1.0f};
        GLfloat sun_light_diffuse[]   = {1.0f, 1.0f, 1.0f, 1.0f};
        GLfloat sun_light_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};

        glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position);
        glLightfv(GL_LIGHT0, GL_AMBIENT,   sun_light_ambient);
        glLightfv(GL_LIGHT0, GL_DIFFUSE,   sun_light_diffuse);
        glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular);

        glEnable(GL_LIGHT0);
        glEnable(GL_LIGHTING);
        glEnable(GL_DEPTH_TEST);
    }

    // 定义太阳的材质并绘制太阳
    {
        GLfloat sun_mat_ambient[]   = {1.0f, 1.0f, 1.0f, 1.0f};
        GLfloat sun_mat_diffuse[]   = {1.0f, 1.0f, 1.0f, 1.0f};
        GLfloat sun_mat_specular[] = {0.0f, 0.0f, 0.0f, 1.0f};
        GLfloat sun_mat_emission[] = {1.0f, 1.0f, 1.0f, 1.0f};
        GLfloat sun_mat_shininess   = 0.0f;

        glMaterialfv(GL_FRONT, GL_AMBIENT,    sun_mat_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE,    sun_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR,   sun_mat_specular);
        glMaterialfv(GL_FRONT, GL_EMISSION,   sun_mat_emission);
        glMaterialf (GL_FRONT, GL_SHININESS, sun_mat_shininess);

        glutSolidSphere(R_Sun, 50, 50);
    }
    // 定义地球的材质并绘制地球
    {
        GLfloat earth_mat_ambient[]   = {0.0f, 0.0f, 0.8f, 1.0f};
        GLfloat earth_mat_diffuse[]   = {0.0f, 0.0f, 0.8f, 1.0f};
        GLfloat earth_mat_specular[] = {0.0f, 0.0f, 0.0f, 1.0f};
        GLfloat earth_mat_emission[] = {0.05f, 0.05f, 0.05f, 1.0f};
        GLfloat earth_mat_shininess   = 80.0f;

        glMaterialfv(GL_FRONT, GL_AMBIENT,    earth_mat_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE,    earth_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR,   earth_mat_specular);
        glMaterialfv(GL_FRONT, GL_EMISSION,   earth_mat_emission);
        glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess);

        glRotatef(day, 0.0f, 0.0f, -1.0f);
        glTranslatef(S_SE, 0.0f, 0.0f);
        glutSolidSphere(R_Earth, 50, 50);
    }


    //绘制月亮
    {
        GLfloat moon_mat_ambient[]   = {0.7f, 0.7f, 0.0f, 1.0f};
        GLfloat moon_mat_diffuse[]   = {0.7f, 0.7f, 0.0f, 1.0f};
        GLfloat moon_mat_specular[] = {0.0f, 0.0f, 0.0f, 1.0f};
        GLfloat moon_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};
        GLfloat moon_mat_shininess   = 40.0f;

        glMaterialfv(GL_FRONT, GL_AMBIENT,    moon_mat_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE,    moon_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR,   moon_mat_specular);
        glMaterialfv(GL_FRONT, GL_EMISSION,   moon_mat_emission);
        glMaterialf (GL_FRONT, GL_SHININESS, moon_mat_shininess);

        glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f);
        glTranslatef(S_EM, 0.0f, 0.0f);
        glutSolidSphere(R_Moon, 50, 50);
    }

    glFlush();
    glutSwapBuffers();
}

void dispchange(int id)
{
    day+=0.5;
    if(day>=360)
        day=0;
    myDisplay();
    glutTimerFunc(16,dispchange,1);
}

void keyboard(unsigned char key,int x,int y)
{
	switch(key)
	{
	case '2':
	    if(Mult_X<5)
            Mult_X+=0.05;
		break;
	case '8':
        if(Mult_X>0.5)
            Mult_X-=0.05;
		break;
	case '4':
	    if(Mult_Y<5)
            Mult_Y+=0.05;
		break;
	case '6':
        if(Mult_Y>0.5)
            Mult_Y-=0.05;
		break;
	case '7':
        if(Mult_Z>0.5)
            Mult_Z+=0.05;
		break;
	case '9':
        if(Mult_Z>0.5)
            Mult_Z-=0.05;
		break;
	case '5':
        Mult_X=1.5;
        Mult_Y=1.5;
        Mult_Z=1.5;
		break;
	}
	glutPostRedisplay();
}

int main(int argc, char *argv[])

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

    glutInitWindowPosition(100, 100);

    glutInitWindowSize(800, 800);

    glutCreateWindow("Sun Earth and Moon");

    glutDisplayFunc(&myDisplay);

    glutTimerFunc(16,dispchange,1);

    glutKeyboardFunc(keyboard);

    glutMainLoop();

    return 0;

}
